/*
This file is part of buco.  
Copyright (c) 2012 Christopher Pawelzik <christopher@cpawelzik.com>

Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 
*/ 
package buco.http;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.http.HttpSession;

import org.json.simple.*;

import buco.core.api.*;
import buco.jsonrpc.*;

public class Dispatcher {
		
	JSONRpcAPI jsonApi; 
	
	public Dispatcher(CompositionContext compositionCtx) {		
		jsonApi = new JSONRpcAPI(compositionCtx); 
	}
	
	@SuppressWarnings({"unchecked", "rawtypes" })
	public JSONObject dispatch(JSONObject request) {
		String version = (String) request.get("jsonrpc");
		if(!version.equals("2.0")) {
			throw new IllegalArgumentException(); 
		}
		
		String methodStr = (String) request.get("method"); 
		int id = ((java.lang.Number)request.get("id")).intValue();		

		// Do we have a parameter and what type is it?
		Object params = null;
		Class args[] = null; 
		if(request.containsKey("params")) {
			args = new Class[1];
			params = request.get("params");			
			if(params instanceof JSONArray) {
				args[0] = JSONArray.class;
			} 
			else if(params instanceof JSONObject) {
				args[0] = JSONObject.class; 
			}
		}
			
		JSONStreamAware result = null; 
		JSONObject error = null; 
					
		try {
			Method method = JSONRpcAPI.class.getMethod(methodStr, args);
			System.out.println("[JSON-RPC] " + methodStr);			
			if(params != null) {				
				result = (JSONStreamAware) method.invoke(jsonApi, params);
			}
			else { 
				result = (JSONStreamAware) method.invoke(jsonApi);
			}
				
		} catch (InvocationTargetException e) {
			error = createErrorObject(e.getTargetException()); 		
		} catch (Exception e) {
			error = createErrorObject(e);			
		}
		
		JSONObject responseObj = new JSONObject(); 
		responseObj.put("jsonrpc", "2.0"); 
		responseObj.put("id", id); 		
		
		if(result != null) {
			responseObj.put("result", result);			  		
		}
		else if(error != null) { 
			responseObj.put("error", error);
		}
		
		return responseObj; 
	}
	
	@SuppressWarnings({ "unchecked" })
	private JSONObject createErrorObject(Throwable e) {
		JSONObject obj = new JSONObject(); 
		obj.put("exception", e.toString());
		
		String message = null; 
		
		if(e instanceof NoBundleException) {
			message = "JAR File is not an OSGi Bundle."; 
		}
		else if(e instanceof DuplicateBundleException) {
			message = "Bundle already exists in the composition."; 
		}
		// .. 
		
		if(message != null) {
			obj.put("message", message);
		}
		
		return obj; 
	}

}
